﻿using ControlHelper;
using ControlHelper.Tools;
using ControlHelper.WPF;
using Creator.Access;
using Creator.Core; 
using Creator.Core.Base;
using Creator.Core.Component;
using DesktopCreator.Controls;
using DesktopCreator.ViewModel;
using HandyControl.Controls;
using HandyControl.Interactivity;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using MessageBox = System.Windows.MessageBox;

namespace DesktopCreator
{
    /// <summary>
    /// Editor.xaml 的交互逻辑
    /// </summary>
    public partial class Editor : System.Windows.Window
    {
        private const double copy_Offset = 25;
        /// <summary>
        /// 当选择对象时
        /// </summary>
        public static Action<BaseObjectViewModel> OnSelectedObject;
        /// <summary>
        /// 当需要绘制的时候，调用会清空编辑界面 canvas的所有数据
        /// </summary> 
        public static Action<IList> DrawData;


        public Editor()
        {
            InitializeComponent();
            Loaded += (s, e) =>
            {
          
                WindowState = WindowState.Maximized; 
                ConfigInit();
                RenderInit(); 
                //-------------------- 事件绑定 ---------------- 
                #region 本地事件绑定


                Hirerachy.OnDoubleClick += (x, y) =>
                {
                    canvasMove.ReSet(gridMain.ActualWidth / 2 - x, gridMain.ActualHeight / 2 - y);
                };

                Editor.OnSelectedObject += (obj) =>
                {
                    if (obj.Object is ProcessObject po)
                    {
                        inspector.SetObjectData(obj);
                        return;
                    }
                    var target = canvas.Children
                     .OfType<FrameworkElement>()
                     .Where(a => a is UCBaseObject ucb && ucb.BaseObject.Id == obj.Object.Id)
                     .FirstOrDefault();

                    SetSelectControl(target);
                };
                Editor.DrawData += (data) =>
                {
                    canvas.Children.Clear();
                    //绘制组件数据
                    var ucp = new UCPanelObjects();
                    ucp.Init(data);

                    canvas.Children.Add(ucp);
                };
                #endregion
            };

        }

        void ConfigInit()
        {
            //canvasMove = new UIElementMove(canvas, this)
            //{
            //    CanMove = true,
            //    CanWhell = true,
            //};

            //初始化加载配置
            SystemData.ProcessObjects = JsonHelper.ReadJson<List<ProcessObject>>(Directory.GetCurrentDirectory() + @"\BaseConfig.json");
            if (SystemData.ProcessObjects == null)
            {
                SystemData.ProcessObjects = new List<ProcessObject>();
            }
            //重新定向引用关系
            foreach (var baseObject in SystemData.ProcessObjects)
            {
                foreach (var behaviour in baseObject.Behaviours)
                {
                    if (behaviour == null) continue;
                    behaviour.BaseObject = SystemData.ProcessObjects.Find(obj => obj.Id == behaviour.BaseObjectId);
                }
            }
            hirerachy.SetData(SystemData.ProcessObjects);
        }
         
        #region 画布操作

        private UIElementMove canvasMove;
        //所有框选的设备集合
        private readonly List<FrameworkElement> selectorList = new List<FrameworkElement>();
        //当前所有控件的集合 存在的目的为了框选时计算是否在框内
        private readonly List<FrameworkElement> controlList = new List<FrameworkElement>();
        private List<Line> allLines = new List<Line>();
        private Point startPoint;
        private Point currentPoint;
        private Rectangle selectorRect;
        //当前选择的控件
        private FrameworkElement currentSelected;
        //同时最多只能有一个新建在场
        private bool haveNew;
        private bool inSelector;

        //当前选择的设备
        private FrameworkElement controlDetail;


        private void AddControl(FrameworkElement fe, bool editor = false)
        {
            if (fe == null) return;
            canvas.Children.Add(fe);
            controlList.Add(fe);
            if (!(fe.DataContext is BaseObject cacheDataContext))
            {
                Growl.Error("错误的BaseObject,添加控件失败!");
                return;
            }
            //允许编辑时
            if (!editor) return;
            var al = AdornerLayer.GetAdornerLayer(fe);
            var adorner = new ElementAdorner(fe);
            al.Add(adorner);

            if (cacheDataContext != null)
            {
                adorner.EnableHorizontal = cacheDataContext.EnableThumbHorizontal;
                adorner.EnableVertical = cacheDataContext.EnableThumbVertical;
            }

            fe.SizeChanged += (s, e) =>
            {
                if (cacheDataContext != null)
                {
                    cacheDataContext.Width = fe.Width;
                    cacheDataContext.Height = fe.Height;
                }
            };


            adorner.DragStarted += (ds, de) =>
            {
                if (selectorList.Count > 1)
                    currentSelected = de as FrameworkElement;
            }; 
            //拖动发生的时候
            adorner.OnDrage += (s, e) =>
            {
                if (cacheDataContext != null)
                {
                    var pos = fe.TransformToAncestor(canvas).Transform(new Point(0, 0));
                    cacheDataContext.PosX = pos.X;
                    cacheDataContext.PosY = pos.Y;
                    cacheDataContext.OnDataChangedCallback?.Invoke(cacheDataContext);
                    if (selectorList.Count <= 1) return;
                    foreach (var item in selectorList)
                    {
                        if (item == currentSelected) continue;
                        Canvas.SetLeft(item, Canvas.GetLeft(item) + e.HorizontalChange);
                        Canvas.SetTop(item, Canvas.GetTop(item) + e.VerticalChange);
                        pos = item.TransformToAncestor(canvas).Transform(new Point(0, 0));
                        var tempDc = item.DataContext as BaseObject;
                        tempDc.PosX = pos.X;
                        tempDc.PosY = pos.Y;
                        tempDc.OnDataChangedCallback?.Invoke(tempDc);
                    }
                }
            };
            //移动四个角时
            adorner.OnMoveDrage += (ds, de) =>
            {
                if (selectorList.Count <= 1) return;
                foreach (var item in selectorList)
                {
                    if (item == ds) continue;
                    item.Width += de.HorizontalChange;
                    item.Height += de.VerticalChange;
                }
            };

        }

        /// <summary>  设置可缩放显示/隐藏 / </summary> 
        private void SetThumShowOrHide(UIElement uiele, bool showOrHide)
        {
            var al = AdornerLayer.GetAdornerLayer(uiele);
            var adorners = al.GetAdorners(uiele);
            if (adorners == null)
            {
                Growl.Info("对应元素未绑定任何装饰器");
                return;
            }
            foreach (var adorner in adorners)
            {
                if (adorner is ElementAdorner ea)
                {
                    if (showOrHide)
                        ea.Show();
                    else
                        ea.Hide();
                    break;
                }
            }
        }


        /// <summary> 添加控件到选择器 </summary> 
        private void AddSelector(FrameworkElement uiele)
        {
            if (!selectorList.Contains(uiele))
            {
                SetThumShowOrHide(uiele, true);
                selectorList.Add(uiele);
            }
        }
        /// <summary>
        /// 从选择器移除已经选择控件
        /// </summary>
        /// <param name="uiele"></param>
        private void RemoveSelector(FrameworkElement uiele)
        {
            if (selectorList.Contains(uiele))
            {
                SetThumShowOrHide(uiele, false);
                selectorList.Remove(uiele);
            }
        }
        /// <summary> 设置当前选中的控件 单击  </summary> 
        private void SetSelectControl(FrameworkElement fe)
        {

            if (currentSelected != null)
            {
                //SetThumShowOrHide(currentSelected, false);
                (currentSelected as UCBaseObject).borderSelect.Visibility = Visibility.Collapsed;
                currentSelected = null;
            }
            if (fe != null && fe.DataContext is BaseObjectViewModel dd)
            {
                (fe as UCBaseObject).borderSelect.Visibility = Visibility.Visible;
                inspector.SetObjectData(dd);
                currentSelected = fe;
                //SetThumShowOrHide(currentSelected, true);
            }
        }

        /// <summary>  检查是否在选择区域内  </summary> >
        private void CheckInSelector(Point startPoint, Point currentPoint)
        {
            if (!inSelector) return;
            foreach (var item in controlList)
            {
                if (item.Parent == null) continue;
                var point = item.TransformToVisual(canvas).Transform(new Point(0, 0));
                if (point.X >= startPoint.X && point.X <= currentPoint.X
                    && point.Y >= startPoint.Y && point.Y <= currentPoint.Y)
                {
                    AddSelector(item);
                }
                else
                {
                    RemoveSelector(item);
                }
            }
        }
        private void SetMouseDown(FrameworkElement fe)
        {
            fe.MouseDown += (s, e) =>
            {
                if (e.LeftButton == MouseButtonState.Pressed)
                {
                    if (inSelector || selectorList.Count > 0)
                    {
                        return;
                    }
                    if (s is FrameworkElement frae)
                    {
                        SetSelectControl(frae);
                    }

                }
            };
        }
        #endregion

        #region 控件渲染 （未完成）

        public class EditorRenderPara
        {
            public FrameworkElement UI { get; set; }
            public RenderComponent Render { get; set; }
            public UIElementMove UIMove { get; set; }

        }

        Dictionary<long, EditorRenderPara> dicRenders = new Dictionary<long, EditorRenderPara>();

        public static Action<RenderComponent> AddRenderComponent;
        public static Action<RenderComponent> RemoveRenderComponent;

        private void RenderInit()
        {

            System.Windows.Threading.DispatcherTimer timer = new System.Windows.Threading.DispatcherTimer()
            {
                Interval = TimeSpan.FromSeconds(1)
            };
            //timer.Tick += Render_Tick;
            AddRenderComponent += AddUI;
            RemoveRenderComponent += RemoveUI;
        }


        public void AddUI(RenderComponent render)
        {
            if (render == null || dicRenders.ContainsKey(render.Id)) return;
            FrameworkElement fe = null;
            UIElementMove um = null;
            if (render is CanvasComponent cc)
            {
                var canvas = new Canvas()
                {
                    HorizontalAlignment = HorizontalAlignment.Left,
                    VerticalAlignment = VerticalAlignment.Top, 
                };
                um = new UIElementMove(canvas, this)
                {
                    CanMove = cc.CanMove,
                    CanWhell = cc.CanWheel
                };
                canvas.DataContext = cc;
                canvas.SetBinding(WidthProperty, ControlHepler.CreateBinding(nameof(cc.Width) ));
                canvas.SetBinding(HeightProperty, ControlHepler.CreateBinding(nameof(cc.Height)));
                canvas.SetBinding(BackgroundProperty, ControlHepler.CreateBinding(nameof(cc.BackBrush)));
                canvas.SetBinding(Panel.ZIndexProperty, ControlHepler.CreateBinding(nameof(cc.ZIndex), UpdateSourceTrigger.PropertyChanged));
                fe = canvas;
            }
            dicRenders.Add(render.Id, new EditorRenderPara()
            {
                Render = render,
                UI = fe,
                UIMove = um,
            });
            //主要控件添加 
            gridMain.Children.Add(fe);
        }

        public void RemoveUI(RenderComponent render)
        {
            if(render == null) return;
            EditorRenderPara para;
            dicRenders.TryGetValue(render.Id, out para);
            if(para == null)
            {
                throw new Exception($"找不到已经参与渲染的组件{render.Id}");
            }

            gridMain.Children.Remove(para.UI);
            dicRenders.Remove(render.Id);
        }

     
 
        #endregion

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            JsonHelper.WriteJson(SystemData.ProcessObjects, Directory.GetCurrentDirectory() + @"\BaseConfig.json"); 
        }

        private void btnBindSet_Click(object sender, RoutedEventArgs e)
        { 
            ItemEditor ieWidnow = new ItemEditor();
            ieWidnow.ShowDialog(); 
        }

        private void Window_Close(object sender, RoutedEventArgs e)
        {
            var result = MessageBox.Show("请确认关闭", "确认", MessageBoxButton.OKCancel, MessageBoxImage.Warning);
            if (result == MessageBoxResult.OK)
            {
                Close(); 
            }
        }

        private void Window_Max(object sender, RoutedEventArgs e)
        {

            this.WindowState = WindowState == WindowState.Normal ? WindowState.Maximized : WindowState.Normal;
        }

        private void Window_Min(object sender, RoutedEventArgs e)
        {
            WindowState = WindowState.Minimized;
        }

        private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            try
            {
                DragMove();
            }
            catch (Exception)
            {
                 
            }
            
            
        }
    }
}
